﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Linq;
using Phoenix.Xna.Framework.Collections;
using Phoenix.Xna.Framework.Properties;
using Phoenix.Xna.Framework.Xml;

namespace Phoenix.Xna.Framework
{
    public class SettingsService : Service, ISettingsService
    {
        private MultiMap<string, ValueBinding> _settings = new MultiMap<string, ValueBinding>();

        public SettingsService()
            : base()
        {
            Initialize();
        }

        public SettingsService(string id)
            : base(id)
        {
            Initialize();
        }

        private void Initialize()
        {
            RootDirectory = "Settings";
            FilePath = "Settings.xml";

            if (Engine.Instance.Services != null)
            {
                Engine.Instance.Services.AddService<ISettingsService>(this);
            }
        }

        private void ParseCategory(XElement element)
        {
            string category = element.ReadAttribute<string>("ID");

            foreach (XNode node in element.Nodes())
            {
                if (node.NodeType == XmlNodeType.Element)
                {
                    XElement e = node as XElement;

                    if (e != null)
                    {
                        ValueBinding v = new ValueBinding();
                        //v.LoadXElement(e);
                        _settings.Add(category, v);
                    }
                }
            }
        }

        #region ISettingsService Members

        public string RootDirectory { get; set; }

        public T GetSetting<T>(string category, string id)
        {
            foreach (ValueBinding v in _settings.GetValues(category))
            {
                if (string.Compare(v.ID, id) == 0)
                {
                    return v.GetValue<T>();
                }
            }

            return default(T);
        }

        #endregion

        #region IFileSerializable Members

        public string FilePath { get; set; }

        public void Load()
        {
            if (string.IsNullOrEmpty(FilePath))
            {
                throw new ArgumentNullException(string.Format(Resources.ArgumentNullException, "FilePath"));
            }

            XElement element = XElement.Load(Path.Combine(RootDirectory, FilePath));
            LoadXElement(element);
        }

        public void Save()
        {
            if (string.IsNullOrEmpty(FilePath))
            {
                throw new ArgumentNullException(string.Format(Resources.ArgumentNullException, "FilePath"));
            }

            ToXElement().Save(Path.Combine(RootDirectory, FilePath));
        }

        #endregion

        #region IXmlSerializable Members

        public void LoadXElement(XElement element)
        {
            foreach (XNode node in element.Nodes())
            {
                if (node.NodeType == XmlNodeType.Element)
                {
                    XElement e = node as XElement;

                    if (e != null)
                    {
                        if (string.Compare(e.Name.ToString(), "Category", true) == 0)
                        {
                            ParseCategory(e);
                        }
                    }
                }
            }
        }

        public void LoadXElement<T>(XElement element, T parameters)
        {
            LoadXElement(element);
        }

        public XElement ToXElement()
        {
            XElement root = new XElement("Settings");

            foreach (KeyValuePair<string, List<ValueBinding>> c in _settings)
            {
                XElement component = new XElement("Category");
                component.SetAttribute("ID", c.Key);

                foreach (ValueBinding v in c.Value)
                {
                    //component.Add(v.ToXElement());
                }

                root.Add(component);
            }

            return root;
        }

        #endregion
    }
}
